package cc.sunni.activiti.controller;

import cc.sunni.activiti.mapper.ActivitiMapper;
import cc.sunni.activiti.util.R;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.activiti.api.process.model.ProcessInstance;
import org.activiti.api.process.runtime.ProcessRuntime;
import org.activiti.api.runtime.shared.query.Page;
import org.activiti.api.runtime.shared.query.Pageable;
import org.activiti.api.task.model.Task;
import org.activiti.api.task.model.builders.TaskPayloadBuilder;
import org.activiti.api.task.runtime.TaskRuntime;
import org.activiti.bpmn.model.FormProperty;
import org.activiti.bpmn.model.UserTask;
import org.activiti.engine.RepositoryService;
import org.apache.commons.lang3.BooleanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * @author jl
 * @since 2021/1/29 20:21
 */
@Api(tags = "任务管理")
@RestController
@RequestMapping("/task")
@Slf4j
public class TaskController {
    @Autowired
    private TaskRuntime taskRuntime;
    @Autowired
    private ProcessRuntime processRuntime;
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private ActivitiMapper activitiMapper;

    @GetMapping(value = "/list")
    @ApiOperation("查询我(当前登录用户)的待办任务")
    public R getTasks() {
        Page<Task> tasks = taskRuntime.tasks(Pageable.of(0, 100));
        List<HashMap<String, Object>> listMap = new ArrayList<>();
        for (Task tk : tasks.getContent()) {
            HashMap<String, Object> hashMap = new HashMap<>();
            hashMap.put("id", tk.getId());
            hashMap.put("name", tk.getName());
            hashMap.put("status", tk.getStatus());
            hashMap.put("createdDate", tk.getCreatedDate());
            hashMap.put("instanceId", tk.getProcessInstanceId());
            hashMap.put("processDefinitionId", tk.getProcessDefinitionId());
            if (tk.getAssignee() == null) {//执行人，null时前台显示未拾取
                hashMap.put("assignee", "待拾取任务");
            } else {
                hashMap.put("assignee", tk.getAssignee());
            }
            ProcessInstance processInstance = processRuntime.processInstance(tk.getProcessInstanceId());
            hashMap.put("instanceName", processInstance.getName());
            listMap.add(hashMap);
        }
        return R.ok(listMap);
    }

    @GetMapping(value = "/completeTask")
    @ApiOperation("完成任务")
    @ApiImplicitParam(name = "taskId", value = "任务ID", required = true, dataTypeClass = String.class)
    public R completeTask(@RequestParam("taskId") String taskId) {
        Task task = taskRuntime.task(taskId);
        if (task.getAssignee() == null) {
            taskRuntime.claim(TaskPayloadBuilder.claim().withTaskId(task.getId()).build());
        }
        taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId(task.getId())
                //.withVariable("k2", "v2")//执行环节设置变量
                .build());
        return R.ok();
    }

    //渲染表单
    @GetMapping(value = "/formDataShow")
    public R formDataShow(@RequestParam("taskId") String taskId) {
        Task task = taskRuntime.task(taskId);
//-----------------------构建表单控件历史数据字典------------------------------------------------
        //本实例所有保存的表单数据HashMap，为了快速读取控件以前环节存储的值
        HashMap<String, String> controlistMap = new HashMap<>();
        //本实例所有保存的表单数据
        List<HashMap<String, Object>> tempControlList = activitiMapper.selectFormData(task.getProcessInstanceId());

        for (HashMap ls : tempControlList) {
            //String Control_ID = ls.get("Control_ID_").toString();
            //String Control_VALUE = ls.get("Control_VALUE_").toString();
            controlistMap.put(ls.get("Control_ID_").toString(), ls.get("Control_VALUE_").toString());
        }

/*  ------------------------------------------------------------------------------
            FormProperty_0ueitp2-_!类型-_!名称-_!默认值-_!是否参数
            例子：
            FormProperty_0lovri0-_!string-_!姓名-_!请输入姓名-_!f
            FormProperty_1iu6onu-_!int-_!年龄-_!请输入年龄-_!s

            默认值：无、字符常量、FormProperty_开头定义过的控件ID
            是否参数：f为不是参数，s是字符，t是时间(不需要int，因为这里int等价于string)
            注：类型是可以获取到的，但是为了统一配置原则，都配置到
            */

        //注意!!!!!!!!:表单Key必须要任务编号一模一样，因为参数需要任务key，但是无法获取，只能获取表单key“task.getFormKey()”当做任务key
        UserTask userTask = (UserTask) repositoryService.getBpmnModel(task.getProcessDefinitionId())
                .getFlowElement(task.getFormKey());

        if (userTask == null) {
            return R.error("无表单");
        }
        List<FormProperty> formProperties = userTask.getFormProperties();
        List<HashMap<String, Object>> listMap = new ArrayList<>();
        for (FormProperty fp : formProperties) {
            String[] splitFP = fp.getId().split("-_!");

            HashMap<String, Object> hashMap = new HashMap<>();
            hashMap.put("id", splitFP[0]);
            hashMap.put("controlType", splitFP[1]);
            hashMap.put("controlLable", splitFP[2]);


            //默认值如果是表单控件ID
            if (splitFP[3].startsWith("FormProperty_")) {
                //控件ID存在
                if (controlistMap.containsKey(splitFP[3])) {
                    hashMap.put("controlDefValue", controlistMap.get(splitFP[3]));
                } else {
                    //控件ID不存在
                    hashMap.put("controlDefValue", "读取失败，检查" + splitFP[0] + "配置");
                }
            } else {
                //默认值如果不是表单控件ID则写入默认值
                hashMap.put("controlDefValue", splitFP[3]);
            }

            hashMap.put("controlIsParam", splitFP[4]);
            listMap.add(hashMap);
        }
        return R.ok(listMap);
    }

    //保存表单
    @PostMapping(value = "/formDataSave")
    public R formDataSave(@RequestParam("taskID") String taskID, @RequestParam("formData") String formData) throws ParseException {
        Task task = taskRuntime.task(taskID);
        //formData:控件id-_!控件值-_!是否参数!_!控件id-_!控件值-_!是否参数
        //FormProperty_0lovri0-_!不是参数-_!f!_!FormProperty_1iu6onu-_!数字参数-_!s
        HashMap<String, Object> variables = new HashMap<>();
        boolean hasVariables = false;//没有任何参数
        List<HashMap<String, Object>> listMap = new ArrayList<>();
        //前端传来的字符串，拆分成每个控件
        String[] formDataList = formData.split("!_!");//
        for (String controlItem : formDataList) {
            String[] formDataItem = controlItem.split("-_!");
            HashMap<String, Object> hashMap = new HashMap<>();
            hashMap.put("PROC_DEF_ID_", task.getProcessDefinitionId());
            hashMap.put("PROC_INST_ID_", task.getProcessInstanceId());
            hashMap.put("FORM_KEY_", task.getFormKey());
            hashMap.put("Control_ID_", formDataItem[0]);
            hashMap.put("Control_VALUE_", formDataItem[1]);
            listMap.add(hashMap);
            //构建参数集合
            switch (formDataItem[2]) {
                case "f":
                    System.out.println("控件值不作为参数");
                    break;
                case "s":
                    variables.put(formDataItem[0], formDataItem[1]);
                    hasVariables = true;
                    break;
                case "t":
                    SimpleDateFormat timeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
                    variables.put(formDataItem[0], timeFormat.parse(formDataItem[2]));
                    hasVariables = true;
                    break;
                case "b":
                    variables.put(formDataItem[0], BooleanUtils.toBoolean(formDataItem[2]));
                    hasVariables = true;
                    break;
                default:
                    log.error("控件参数类型配置错误：{}的参数类型不存在，{}", formDataItem[0], formDataItem[2]);
            }
        }
        if (hasVariables) {
            //带参数完成任务
            taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId(taskID)
                    .withVariables(variables)
                    .build());
        } else {
            taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId(taskID)
                    .build());
        }
        activitiMapper.insertFormData(listMap);
        return R.ok(listMap);
    }
}
